package com.sun.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.common.Exception.CustomException;
import com.sun.dto.InstoreDto;
import com.sun.entity.*;
import com.sun.mapper.InstoreMapper;
import com.sun.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Project: hospitalDrugInformationManagement
 * @Author: 86178
 * @Date: 2023/3/21 15:27
 * @FileName: InstoreServiceImpl
 * @Description: ""
 */
@SuppressWarnings("all")
@Service
public class InstoreServiceImpl extends ServiceImpl<InstoreMapper, Instore> implements InstoreService {
    @Autowired
    private InstoreDetailService instoreDetailService;
    @Autowired
    private InstoreMapper instoreMapper;
    @Autowired
    private PurchaseHeadService purchaseHeadService;
    @Autowired
    private StoreService storeService;
    @Autowired
    private DrugService drugService;

    @Override
    public IPage<InstoreDto> selectInstoreDtoListPage(IPage<InstoreDto> page, String userName, Integer status, Integer type, String addr, LocalDateTime startTime, LocalDateTime endTime) {
        return instoreMapper.selectInstoreDtoListPage(page, userName, status, type, addr, startTime, endTime);
    }

    @Override
    public void saveWithInstoreDetail(InstoreDto instoreDto) {
        //保存入库的基本信息，操作instore，执行insert操作
        instoreDto.setStatus(0);
        boolean save = this.save(instoreDto);
        //保存入库表单目
        List<InstoreDetail> instroreDetails = instoreDto.getInstoreDetails();
        instroreDetails.stream().map((item) -> {
            item.setReceiptId(instoreDto.getReceiptId());
            Drug drug = drugService.getById(item.getDrugId());
            item.setValidityPeriod(drug.getValidityPeriod());
            return item;
        }).collect(Collectors.toList());

        boolean b = instoreDetailService.saveBatch(instroreDetails);
        //加入入库单的采购计划应该标记为入库
        List<PurchaseHead> purchaseHeadList = instoreDto.getPurchaseHeads();
        for (PurchaseHead item : purchaseHeadList) {
            item.setStatus(3);
            item.setReceiptId(instoreDto.getReceiptId());
        }
        purchaseHeadService.updateBatchById(purchaseHeadList);
    }

    @Override
    public void updateWithInstoreDetail(InstoreDto instoreDto) {
        //先更新入库单单头的信息
        this.updateById(instoreDto);
        //再更新入库单单目的信息
        //先把入库单目查询出来和新的比较如果存在就更新，不存在就新增，新的数据没有就删除
        //查询历史数据
        LambdaQueryWrapper<InstoreDetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(InstoreDetail::getReceiptId, instoreDto.getReceiptId());
        List<InstoreDetail> oldData = instoreDetailService.list(lambdaQueryWrapper);
        //新的数据
        List<InstoreDetail> dtoInstoreDetails = instoreDto.getInstoreDetails();
        //进行比较
        // 遍历新数据列表
        for (InstoreDetail newData : dtoInstoreDetails) {
            boolean flag = true; // 是否需要新增
            int i = 0; // 在历史数据列表中的位置
            // 遍历历史数据列表
            for (i = 0; i < oldData.size(); i++) {
                InstoreDetail oldInstoreDetail = oldData.get(i);
                // 比较历史数据和新数据
                if (newData.getId() != null && newData.getId().equals(oldInstoreDetail.getId())) {
                    // 需要更新
                    flag = false;
                    instoreDetailService.updateById(newData);
                    break;
                }
            }
            if (flag) {
                // 需要新增
                newData.setReceiptId(instoreDto.getReceiptId());
                instoreDetailService.save(newData);
            }
        }

        for (InstoreDetail oldItem : oldData) {
            boolean exist = false; // 是否存在于新数据列表中
            // 判断历史数据是否存在于新数据列表中
            for (InstoreDetail item : dtoInstoreDetails) {
                if (oldItem.getId().equals(item.getId())) {
                    exist = true;
                    break;
                }
            }
            if (!exist) {
                // 需要删除
                instoreDetailService.removeById(oldItem.getId());
            }
        }
    }


    @Override
    public InstoreDto getByIdWithInstoreDetail(Long id) {
        InstoreDto instoreDto = new InstoreDto();
        //查询入库单基本信息，从instore表查询
        Instore instore = this.getById(id);
        BeanUtils.copyProperties(instore, instoreDto);

        //查询当前入库单对应的药品信息，从instore_detail表查询
        LambdaQueryWrapper<InstoreDetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(InstoreDetail::getReceiptId, instore.getReceiptId());
        List<InstoreDetail> instoreDetails = instoreDetailService.list(lambdaQueryWrapper);
        instoreDto.setInstoreDetails(instoreDetails);

        return instoreDto;
    }

    @Override
    public void batchDeleteByIds(List<Long> ids) {
        //查询入库单状态，确定是否可用删除
        LambdaQueryWrapper<Instore> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.in(Instore::getReceiptId, ids);
        lambdaQueryWrapper.eq(Instore::getStatus, 1);

        int count = this.count(lambdaQueryWrapper);
        if (count > 0) {
            //如果不能删除，抛出一个业务异常
            throw new CustomException("入库单已完成不能删除");
        }

        //如果可以删除，先删除入库单头表中的数据---purchase_head
        this.removeByIds(ids);

        //delete from instore_detail where receipt_id in (1,2,3)
        LambdaQueryWrapper<InstoreDetail> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper1.in(InstoreDetail::getReceiptId, ids);
        //删除关系表中的数据----instore_detail
        instoreDetailService.remove(lambdaQueryWrapper1);

        //更改采购单的状态 把入库改为已完成
        PurchaseHead purchaseHead = new PurchaseHead();
        purchaseHead.setStatus(2);
        purchaseHead.setReceiptId(null);
        LambdaQueryWrapper<PurchaseHead> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper2.in(PurchaseHead::getReceiptId, ids);
        purchaseHeadService.update(purchaseHead, lambdaQueryWrapper2);
    }

    @Override
    public void updateStatusByIds(List<Long> ids) {
        //  修改入库单状态为完成状态，更新库存
        LambdaQueryWrapper<Instore> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(ids != null, Instore::getReceiptId, ids);

        List<Instore> instoreList = this.list(lambdaQueryWrapper);
        if (instoreList != null) {
            for (Instore item : instoreList) {
                item.setStatus(1);
                this.updateById(item);
                //更新库存,直接给库存表中新增记录
                LambdaQueryWrapper<InstoreDetail> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                lambdaQueryWrapper1.eq(InstoreDetail::getReceiptId, item.getReceiptId());
                List<InstoreDetail> instoreDetails = instoreDetailService.list(lambdaQueryWrapper1);
                List<Store> storeList = instoreDetails.stream().map(it -> {
                    Store store = new Store();
                    LocalDateTime usefulDate = it.getProductionDate().minusMonths(-Long.parseLong(it.getValidityPeriod()));

                    store.setDrugId(it.getDrugId());
                    store.setDrugName(it.getDrugName());
                    store.setDrugCode(it.getDrugCode());
                    store.setDrugNumber(it.getNum());
                    store.setIntime(LocalDateTime.now());
                    store.setUsefulDate(usefulDate);
                    store.setInprice(it.getPrice());
                    store.setOutprice(String.valueOf(Double.valueOf(it.getPrice()) * 2));
                    store.setSingleunit(it.getSingleunit());
                    store.setAddr(item.getAddr());
                    store.setSupplierId(it.getSupplierId());
                    store.setSupplierName(it.getSupplierName());

                    return store;
                }).collect(Collectors.toList());
                storeService.saveBatch(storeList);
            }
        }
    }
}
